home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
os2
/
pmnos11s
/
rarp.c
< prev
next >
Wrap
Text File
|
1993-07-30
|
6KB
|
218 lines
/* Reverse Address Resolution Protocol (ARP) functions. Sits between IP and
* Level 2, mapping Level 2 addresses to IP.
*/
#include "global.h"
#include "mbuf.h"
#include "proc.h"
#include "timer.h"
#include "iface.h"
#include "socket.h"
#include "ax25.h"
#include "arp.h"
#include "netuser.h"
#include "cmdparse.h"
#include "pktdrvr.h"
struct arp_stat Rarp_stat;
static int Rwaiting = 0; /* Semaphore used when waiting for a reply */
static void arp_output __ARGS((struct iface *iface,int16 hardware,char *hwaddr,char *target));
static int dorarpquery __ARGS((int argc,char *argv[],void *p));
static void rarpstat __ARGS((void));
static void rarp_output __ARGS((struct iface *iface,int16 hardware,char *hwaddr,char *target));
static struct cmds Rarpcmds[] = {
"query", dorarpquery, 0, 3,
#ifdef fixed
"rarp query <interface> <ether addr|callsign> [<ether addr|callsign>]",
#else
"rarp query <interface> <callsign> [<ether addr|callsign>]",
#endif
NULLCHAR
};
int
dorarp(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc < 2){
rarpstat();
return 0;
}
return subcmd(Rarpcmds,argc,argv,p);
}
static int
dorarpquery(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
char hwaddr[MAXHWALEN], qhwaddr[MAXHWALEN];
int16 hardware, t;
static char *errmsg = "Illegal hardware address\n";
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf(Badinterface,argv[1]);
return -1;
}
switch(ifp->iftype->type) {
case CL_AX25:
hardware = ARP_AX25;
break;
#ifdef fixed
case CL_ETHERNET:
hardware = ARP_ETHER;
break;
default:
tputs("Only Ethernet and AX25 interfaces allowed\n");
#else
default:
tputs("Only AX25 interfaces allowed\n");
#endif
return -1;
}
if((*ifp->iftype->scan)(hwaddr,argv[2]) == -1) {
tputs(errmsg);
return -1;
}
if(argc > 3 && (*ifp->iftype->scan)(qhwaddr,argv[3]) == -1) {
tputs(errmsg);
return -1;
}
if(argc == 3)
memcpy(qhwaddr,hwaddr,ifp->iftype->hwalen);
rarp_output(ifp,hardware,hwaddr,qhwaddr);
t = Arp_type[hardware].pendtime;
++Rwaiting;
tprintf("Trying... %2d",t);
while(t--) {
alarm(1000L);
if(pwait(&Rwaiting) != EALARM) {
alarm(0);
--Rwaiting;
return 0;
}
tprintf("\b\b%2d",t);
}
tputs("\b\bTimeout.\n");
--Rwaiting;
return 0;
}
/* Handle incoming RARP packets according to RFC 903.
*/
void
rarp_input(iface,bp)
struct iface *iface;
struct mbuf *bp;
{
struct arp rarp;
struct arp_type *at;
char shwaddr[MAXHWALEN];
Rarp_stat.recv++;
if(ntoharp(&rarp,&bp) == -1) /* Convert into host format */
return;
if(rarp.hardware >= NHWTYPES){
/* Unknown hardware type, ignore */
Rarp_stat.badtype++;
return;
}
at = &Arp_type[rarp.hardware];
if(rarp.protocol != at->iptype){
/* Unsupported protocol type, ignore */
Rarp_stat.badtype++;
return;
}
if(uchar(rarp.hwalen) > MAXHWALEN || uchar(rarp.pralen) != sizeof(int32)){
/* Incorrect protocol addr length (different hw addr lengths
* are OK since AX.25 addresses can be of variable length)
*/
Rarp_stat.badlen++;
return;
}
if(memcmp(rarp.shwaddr,at->bdcst,at->hwalen) == 0){
/* This guy is trying to say he's got the broadcast address! */
Rarp_stat.badaddr++;
return;
}
if(rarp.opcode == REVARP_REQUEST) {
/* We are not a server, so we can only answer requests for a
* hardware address that is our own. But would be possible to
* use the ARP table to answer requests for someone elses
* IP address.
*/
if(memcmp(rarp.thwaddr,iface->hwaddr,at->hwalen) == 0) {
memcpy(shwaddr,rarp.shwaddr,at->hwalen);
/* Mark the end of the sender's AX.25 address
* in case he didn't
*/
if(rarp.hardware == ARP_AX25)
rarp.thwaddr[uchar(rarp.hwalen)-1] |= E;
memcpy(rarp.shwaddr,iface->hwaddr,at->hwalen);
rarp.sprotaddr = iface->addr;
rarp.tprotaddr = iface->addr;
rarp.opcode = REVARP_REPLY;
if((bp = htonarp(&rarp)) == NULLBUF)
return;
if(iface->forw != NULLIF)
(*iface->forw->output)(iface->forw,shwaddr,
iface->forw->hwaddr,at->rarptype,bp);
else
(*iface->output)(iface,shwaddr,
iface->hwaddr,at->rarptype,bp);
Rarp_stat.inreq++;
}
} else {
Rarp_stat.replies++;
if(Rwaiting) {
psignal(&Rwaiting,1);
tprintf("\nRARP Reply: %s %s\n",
(*at->format)(shwaddr,rarp.thwaddr),
inet_ntoa(rarp.tprotaddr));
}
}
}
/* Send a RARP request to target to resolve hardware address hwaddr */
static void
rarp_output(struct iface *iface,int16 hardware, char *hwaddr,char *target)
{
struct arp rarp;
struct mbuf *bp;
struct arp_type *at;
at = &Arp_type[hardware];
// if(iface->output == NULLFP)
if(iface->output == 0)
return;
rarp.hardware = hardware;
rarp.protocol = at->iptype;
rarp.hwalen = at->hwalen;
rarp.pralen = sizeof(int32);
rarp.opcode = REVARP_REQUEST;
memcpy(rarp.shwaddr,iface->hwaddr,at->hwalen);
rarp.sprotaddr = 0;
memcpy(rarp.thwaddr,hwaddr,at->hwalen);
rarp.tprotaddr = 0;
if((bp = htonarp(&rarp)) == NULLBUF)
return;
(*iface->output)(iface,target,
iface->hwaddr,at->rarptype,bp);
Rarp_stat.outreq++;
}
static void
rarpstat()
{
tprintf("received %u badtype %u bogus addr %u reqst in %u replies %u reqst out %u\n",
Rarp_stat.recv,Rarp_stat.badtype,Rarp_stat.badaddr,Rarp_stat.inreq,
Rarp_stat.replies,Rarp_stat.outreq);
}